package org.osll.tictactoe.transport.corba.client;

import 
org.omg.CORBA.ORB;
import org.omg.CORBA.ORBPackage.InvalidName;
import org.omg.CosNaming.NamingContextExt;
import org.omg.CosNaming.NamingContextExtHelper;
import org.omg.CosNaming.NamingContextPackage.CannotProceed;
import org.omg.CosNaming.NamingContextPackage.NotFound;
import org.osll.tictactoe.Control;
import org.osll.tictactoe.CurrentMove;
import org.osll.tictactoe.Move;
import org.osll.tictactoe.Size;
import org.osll.tictactoe.Team;
import org.osll.tictactoe.engine.MoveImpl;
import org.osll.tictactoe.transport.DefaultOptions;
import org.osll.tictactoe.transport.corba.Adapter;
import org.osll.tictactoe.transport.corba.service.ControlHelper;
import org.osll.tictactoe.transport.corba.service.ErrorException;

public class ControlImpl implements Control {

	private org.osll.tictactoe.transport.corba.service.Control service = null;
	private String name;
	private Team team;
	
	public ControlImpl(String serviceName, String name, Team team) {
		this.name = name;
		this.team = team;
		String args[] = new String[5];
		args[0] = "";
		args[1] = "-ORBInitialPort";
		args[2] = "1050";
		args[3] = "-ORBInitialHost";
		args[4] = DefaultOptions.getInstance().getHost();

	    // create and initialize the ORB
	    ORB orb = ORB.init(args, null);

	    // get the root naming context
	    org.omg.CORBA.Object objRef = null;
		try {
			objRef = orb.resolve_initial_references("NameService");
		} catch (InvalidName e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		  
	    // Use NamingContextExt instead of NamingContext. This is 
	    // part of the Interoperable naming Service.  
	    NamingContextExt ncRef = NamingContextExtHelper.narrow(objRef);
	 
	    // resolve the Object Reference in Naming
	    try {
			service = ControlHelper.narrow(ncRef.resolve_str(serviceName));
			try {
				service.connect(name, Adapter.convertTeam(team));
			} catch (ErrorException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		} catch (NotFound e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (CannotProceed e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (org.omg.CosNaming.NamingContextPackage.InvalidName e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	@Override
	synchronized public void disconnect() {
	}

	@Override
	synchronized public Move getApponentMove() {
		Move r = null;
		try {
			Team t = Team.U;
			if(team == Team.X)
				t=Team.O;
			else
				t=Team.X;				
			r = Adapter.convertMove(service.getApponentMove(Adapter.convertTeam(t)));
		} catch (ErrorException e) {
			throw (IllegalStateException) Adapter.getException(e.description);
		}
		return r;
	}

	@Override
	synchronized public String getApponentName() {
		Team t = Team.U;
		if(team == Team.X)
			t = Team.O;
		else
			t = Team.X;
		String r = null;
		try {
			r = service.getApponenName(Adapter.convertTeam(t));
		} catch (ErrorException e) {
			throw (IllegalStateException) Adapter.getException(e.description);
		}
		return r;
	}

	@Override
	synchronized public CurrentMove getMoveEndTime() {
		CurrentMove r = null;
		try {
			r = Adapter.convertCurrentMove(service.getMoveEndTime());
		} catch (ErrorException e) {
			throw (IllegalStateException) Adapter.getException(e.description);
		}
		return r;
	}

	@Override
	synchronized public Size getSize() {
		Size r = null;
		try {
			r = Adapter.convertSize(service.getSize());
		} catch (ErrorException e) {
			throw (IllegalStateException) Adapter.getException(e.description);
		}
		return r;
	}

	@Override
	synchronized public boolean isOver() {
		try {
			return service.isOver();
		} catch (ErrorException e) {
			throw (IllegalStateException) Adapter.getException(e.description);
		}
	}

	@Override
	synchronized public boolean isStarted() {
		try {
			return service.isStarted();
		} catch (ErrorException e) {
			throw (IllegalStateException) Adapter.getException(e.description);
		}
	}

	@Override
	synchronized public void makeMove(int row, int col) {
		try {
			service.makeMove(Adapter.convertMove(new MoveImpl(row,col,team)));
		} catch (ErrorException e) {
			throw (IllegalStateException) Adapter.getException(e.description);
		}
	}

}
